package com.quanyan.stadiumScheduler.service.impl;

import com.google.gson.Gson;
import com.quanyan.api.APIRequest;
import com.quanyan.api.APIResponse;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.utils.CommonUtils;
import com.quanyan.common.utils.DateUtils;
import com.quanyan.common.Plugin.Page;
import com.quanyan.orderpay.request.ReqOrderRefund;
import com.quanyan.orderpay.request.ReqRefundPayInfo;
import com.quanyan.orderpay.request.ReqRefundProduct;
import com.quanyan.orderpay.service.OrderPayService;
import com.quanyan.pay.enums.PayWayEnum;
import com.quanyan.pay.enums.RefundStatusEnum;
import com.quanyan.stadiumScheduler.biz.BizGameSystemDao;
import com.quanyan.stadiumScheduler.constants.GameConstants;
import com.quanyan.stadiumScheduler.entity.*;
import com.quanyan.stadiumScheduler.entity.TbGameEvent;
import com.quanyan.stadiumScheduler.enums.GameTypeConfigEnum;
import com.quanyan.stadiumScheduler.mapper.TbGameEventMapper;
import com.quanyan.stadiumScheduler.mapper.TbGameEventTeamMapper;
import com.quanyan.stadiumScheduler.mapper.TbGameOrderMapper;
import com.quanyan.stadiumScheduler.mapper.TbGameScheduleMapper;
import com.quanyan.stadiumScheduler.service.GameEventService;
import com.quanyan.stadiumScheduler.service.GameMsgPush;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @author lds
 * @date 2017/2/14 14:42
 */

@Service
public class GameEventServiceImpl implements GameEventService {


    @Autowired
    private BizGameSystemDao bizGameSystemDao;

    @Autowired
    private GameMsgPush gameMsgPush;

    @Autowired
    private TbGameEventMapper tbGameEventMapper;

    @Autowired
    private TbGameScheduleMapper tbGameScheduleMapper;

    @Autowired
    private TbGameEventTeamMapper tbGameEventTeamMapper;

    @Autowired
    private TbGameOrderMapper tbGameOrderMapper;

    @Autowired
    private OrderPayService orderPayService;

    @Value("${stadium.refund.url}")
    private String refundUrl;

    private static final Gson gson = new Gson();

    private static Logger logger = LoggerFactory.getLogger(GameEventServiceImpl.class);

    @Override
    public void lockScoreAndEndPersonalGameEvents() {
        Date seventDate = DateUtils.addNDay(new Date(), -7);
        TbGameEventExample example = new TbGameEventExample();
        TbGameEventExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(GameConstants.IS_NOT_DELETE);
        //创建者：个人
        criteria.andTypeEqualTo(GameConstants.PERSONAL_CREATE);
        //赛事类型：
        criteria.andGameEventTypeEqualTo((byte)GameTypeConfigEnum.CONFIG_GAME_EVENT_TYPE_PERSONAL.getId());
        criteria.andInventoryLevelEqualTo(0);
        criteria.andCurrentRoundIdGreaterThan(0);
        criteria.andStartTimeLessThanOrEqualTo(seventDate);
        example.setPage(new Page(0,50));
        List<TbGameEvent> gameEventList = tbGameEventMapper.selectByExample(example);
        if(null != gameEventList && gameEventList.size() > 0){
            for(TbGameEvent tbGameEvent : gameEventList){
                List<TbGameRound> tbGameRoundList  = bizGameSystemDao.selectTbGameRoundByGameEventId(tbGameEvent.getId());
                if(null != tbGameRoundList && tbGameRoundList.size() > 0) {
                    TbGameRound gameRound = tbGameRoundList.get(0);
                    List<TbGameSchedule> gameScheduleList = bizGameSystemDao.selectTbGameScheduleByGameRoundId(gameRound.getId(), 0, 1);
                    if (null != gameEventList && gameEventList.size() > 0) {
                        TbGameSchedule tbGameSchedule = gameScheduleList.get(0);
                        TbGameEvent gameEvent = new TbGameEvent();
                        TbGameSchedule gameSchedule = new TbGameSchedule();
                        gameSchedule.setId(tbGameSchedule.getId());
                        if (tbGameSchedule.getStatus() == GameConstants.RECORD_WAIT) {
                            gameEvent.setCurrentRoundId(-1);
                        } else if (tbGameSchedule.getStatus() == GameConstants.RECORD_WAIT_SURE || tbGameSchedule.getStatus() == GameConstants.RECORD_SECOND_WAIT_SURE) {
                            gameEvent.setCurrentRoundId(-1);
                            gameSchedule.setStatus(GameConstants.RECORD_SUCCESS);
                            tbGameScheduleMapper.updateByPrimaryKeySelective(gameSchedule);
                        }
                        tbGameEventMapper.updateByExampleSelective(gameEvent, example);

                        //比赛结束，通知参赛人员
                        TbGameEventTeamExample eventTeamExample = new TbGameEventTeamExample();
                        TbGameEventTeamExample.Criteria criteria_team = eventTeamExample.createCriteria();
                        criteria_team.andGameEventIdEqualTo(tbGameEvent.getId());
                        List<TbGameEventTeam> tbGameEventTeamList = tbGameEventTeamMapper.selectByExample(eventTeamExample);
                        if(null != tbGameEventTeamList && tbGameEventTeamList.size() > 0){
                            List<Integer> uids = new ArrayList<>();
                            for(TbGameEventTeam tbGameEventTeam : tbGameEventTeamList){
                                uids.add(tbGameEventTeam.getUid());
                            }
                            gameMsgPush.pushGameFinishPushMsgToUser(tbGameEvent,uids);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void endPersonalGameEvents() {
        Date currentTime = new Date();
        TbGameEvent gameEvent = new TbGameEvent();
        gameEvent.setCurrentRoundId(-1);

        TbGameEventExample example = new TbGameEventExample();
        TbGameEventExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(GameConstants.IS_NOT_DELETE);
        criteria.andTypeEqualTo(GameConstants.PERSONAL_CREATE);
        criteria.andInventoryLevelGreaterThan(0);
        criteria.andStartTimeLessThanOrEqualTo(currentTime);
        criteria.andCurrentRoundIdNotEqualTo(-1);
        example.setPage(new Page(0,50));
        List<TbGameEvent> tbGameEventList = tbGameEventMapper.selectByExample(example);
        if(null != tbGameEventList && tbGameEventList.size() > 0 ){
            List<Integer> uids = new ArrayList<>();
            for(TbGameEvent tbGameEvent : tbGameEventList){
                uids.clear();
                uids.add(tbGameEvent.getUid());
                if(uids.size() > 0 && null != tbGameEvent){
                    gameMsgPush.unNormalEnd(tbGameEvent,uids);
                }
            }
        }

        tbGameEventMapper.updateByExampleSelective(gameEvent,example);
    }

    @Override
    public void clubGameEventsSystemCancel() {
        //七天时间
        Date seventDate = DateUtils.addNDay(new Date(), -7);
        TbGameEventExample example = new TbGameEventExample();
        TbGameEventExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(GameConstants.IS_NOT_DELETE);
        //创建者：俱乐部
        criteria.andTypeEqualTo(GameConstants.CLUB_CREATE);
        //赛事类型：内部赛
        criteria.andGameEventTypeEqualTo((byte)GameTypeConfigEnum.CONFIG_GAME_EVENT_TYPE_INTERNAL.getId());
        criteria.andCurrentRoundIdEqualTo(0);
        criteria.andStartTimeLessThanOrEqualTo(seventDate);
        example.setPage(new Page(0,20));
        List<TbGameEvent> gameEventList = tbGameEventMapper.selectByExample(example);
        if(null != gameEventList && gameEventList.size() > 0){
            TbGameEvent gameEvent = new TbGameEvent();
            gameEvent.setIsDelete(GameConstants.DELETE_BY_SYSTEM);
            gameEvent.setCurrentRoundId(-1);
            tbGameEventMapper.updateByExampleSelective(gameEvent,example);

            //比赛结束，通知参赛人员
            for(TbGameEvent tbGameEvent : gameEventList){
                TbGameEventTeamExample eventTeamExample = new TbGameEventTeamExample();
                TbGameEventTeamExample.Criteria criteria_team = eventTeamExample.createCriteria();
                criteria_team.andGameEventIdEqualTo(tbGameEvent.getId());
                List<TbGameEventTeam> tbGameEventTeamList = tbGameEventTeamMapper.selectByExample(eventTeamExample);
                if(null != tbGameEventTeamList && tbGameEventTeamList.size() > 0){
                    List<Integer> uids = new ArrayList<>();
                    for(TbGameEventTeam tbGameEventTeam : tbGameEventTeamList){
                        uids.add(tbGameEventTeam.getUid());
                    }
                    gameMsgPush.pushGameFinishPushMsgToUser(tbGameEvent,uids);
                }
                //给报名参赛用户退款
                refound(tbGameEvent.getId());
            }
        }
    }

    public void refound(Integer gameId) {
        logger.info("开始给已经报名比赛gameid={}的用户退款", gameId);
        TbGameEvent tbGameEvent = tbGameEventMapper.selectByPrimaryKey(gameId);
        if (tbGameEvent == null) {
            logger.error("比赛不存在,不能退款！");
        }

        TbGameOrderExample example = new TbGameOrderExample();
        TbGameOrderExample.Criteria criteria = example.createCriteria();
        criteria.andGameEventIdEqualTo(gameId);
        criteria.andIsCloseEqualTo(GameConstants.ORDER_IS_CLOST_YES);
        criteria.andPayWaitEqualTo(GameConstants.SUCCESS_PAY);
        criteria.andOrderStatusEqualTo(GameConstants.SUCCESS_ORDER);
        List<TbGameOrder> orders = tbGameOrderMapper.selectByExample(example);

        if (!CollectionUtils.isEmpty(orders)) {
            logger.info("查询到支付成功的订单{}个需要退订，下面开始退款：", orders.size());
            for (TbGameOrder order : orders) {
                logger.info("给用户报名用户uid={}退款，需要退人民币：{},鸟蛋:{}", order.getUid(), order.getPayAmount(), order.getAccumulate());
                refoundUserPay(order, tbGameEvent);
                onRefund(order.getTradeOrderNo());
            }
        }
    }

    /**
     * 调用订单系统给用户退款
     */
    public APIResponse<RefundStatusEnum> refoundUserPay(TbGameOrder order, TbGameEvent tbGameEvent) {
        if (order.getOrderAmount().doubleValue() == 0) {
            successRefund(order.getTradeOrderNo());
            return APIResponse.returnSuccess();
        }
        APIRequest<ReqOrderRefund> orderRefundAPIRequest = new APIRequest<>();
        ReqOrderRefund reqOrderRefund = new ReqOrderRefund();
        reqOrderRefund.setSourceSystemId(Constants.STADIUM_SYSTEM_CODE);
        reqOrderRefund.setSourceBusinessId(Constants.STADIUM_GAME_SIGN_BUSINESS_CODE);
        reqOrderRefund.setOrderNo(order.getGameOrderNo());
        reqOrderRefund.setOutTradeRefundNo("REFUND_" + CommonUtils.generateOrderNo(order.getUid()));
        reqOrderRefund.setReason("比赛取消");
        reqOrderRefund.setUid(order.getUid());
        reqOrderRefund.setRefundNotifyURL(refundUrl);
        reqOrderRefund.setNeedAudit(false);

        DecimalFormat df = new DecimalFormat("#####.00");
        reqOrderRefund.setAmount(new BigDecimal(df.format(order.getOrderAmount())));
        //退款产品
        List<ReqRefundProduct> reqRefundProducts = new ArrayList<>();
        ReqRefundProduct reqRefundProduct = new ReqRefundProduct();

        reqRefundProduct.setPrice(tbGameEvent.getPrice());

        reqRefundProduct.setQuantity(1);
        reqRefundProduct.setProductName(tbGameEvent.getName());
        reqRefundProduct.setProductId(tbGameEvent.getId().toString());
        reqRefundProducts.add(reqRefundProduct);

        List<ReqRefundPayInfo> reqRefundPayInfoList = new ArrayList<ReqRefundPayInfo>();
        if (order.getPayAmount().doubleValue() > 0) {
            ReqRefundPayInfo rmb = new ReqRefundPayInfo();
            rmb.setPayId(order.getPayType().intValue());
            rmb.setRefundAmount(new BigDecimal(df.format(order.getPayAmount())));
            reqRefundPayInfoList.add(rmb);
        }
        if (order.getAccumulate() > 0) {
            ReqRefundPayInfo ages = new ReqRefundPayInfo();
            ages.setPayId(PayWayEnum.PAY_WAY_FOR_AGES.getPayId());
            ages.setRefundAmount(BigDecimal.valueOf(order.getAccumulate()));
            reqRefundPayInfoList.add(ages);
        }
        reqOrderRefund.setReqRefundPayInfos(reqRefundPayInfoList);
        reqOrderRefund.setRefundProductList(reqRefundProducts);
        orderRefundAPIRequest.setData(reqOrderRefund);
        APIResponse<RefundStatusEnum> response = orderPayService.refundApply(orderRefundAPIRequest);
        logger.info("退款响应：{}", gson.toJson(response.getData()));
        onRefund(order.getGameOrderNo());
        return response;
    }


    /**
     * 申请退款中
     *
     * @param orderNo
     */
    private void onRefund(String orderNo) {
        TbGameOrderExample tbGameOrderExample = new TbGameOrderExample();
        TbGameOrderExample.Criteria criteria = tbGameOrderExample.createCriteria();
        criteria.andTradeOrderNoEqualTo(orderNo);
        TbGameOrder tbGameOrder = new TbGameOrder();
        tbGameOrder.setOrderStatus(GameConstants.ON_REFUND);
        tbGameOrder.setRefundTime(new Date());
        tbGameOrderMapper.updateByExampleSelective(tbGameOrder, tbGameOrderExample);
    }

    /**
     * 申请退款成功
     *
     * @param orderNo
     */
    private void successRefund(String orderNo) {
        TbGameOrderExample tbGameOrderExample = new TbGameOrderExample();
        TbGameOrderExample.Criteria criteria = tbGameOrderExample.createCriteria();
        criteria.andTradeOrderNoEqualTo(orderNo);
        TbGameOrder tbGameOrder = new TbGameOrder();
        tbGameOrder.setOrderStatus(GameConstants.SUCCESS_REFUND);
        tbGameOrderMapper.updateByExampleSelective(tbGameOrder, tbGameOrderExample);
    }
}
